@isTest
public class ChatterUserTriggerHelperTest 
{
	public static User GetTestUser()
	{
		String uniqueToken = String.valueOf((Integer)(Math.random() * 1000));
		
		User u = new User();
      u.UserName = 'test@test' + uniqueToken + '.att-temp.com';
      u.LastName = 'test' + uniqueToken;
      u.Email = u.UserName;
      u.Alias = 'ua' + uniqueToken;
      u.CommunityNickname = 'ua' + uniqueToken;
      u.TimeZoneSidKey = 'America/Los_Angeles';
      u.LocaleSidKey = 'en_US';
      u.EmailEncodingKey = 'UTF-8';
      u.LanguageLocaleKey = 'en_US';
      u.IsActive = true;
      
      return u;
	}
	
	@isTest
	private static void testAllUserChatterAssignment()
	{
		Map<Id,Profile> pMap = new Map<Id,Profile>([SELECT Id, Name FROM Profile]);
		Map<Id,UserRole> urMap = new Map<Id,UserRole>([SELECT Id, Name FROM UserRole]);
		Map<Id,User> sysAdmins = new Map<Id,User>([SELECT Id, Profile.Name, UserRole.Name, UserRoleId FROM User WHERE IsActive = true AND Profile.Name = 'System Administrator']);
		
		Id oorProfileId = null;
		for(Profile p : pMap.values())
		{
			if(ChatterUserTriggerHelper.OOR_CHATTER_DISTRO_PROFILES.contains(p.Name))
			{
				oorProfileId = p.Id;
				break;
			}
		}
		
		Id testProfileId = pMap.values()[0].Id;
		Id testRoleId = urMap.values()[0].Id;
		User testSysAdmin = sysAdmins.values()[0];
		
		CollaborationGroup testCG1 = new CollaborationGroup();
		testCG1.Name = 'test Chatter Group 1';
		testCG1.CollaborationType = 'private';
		testCG1.OwnerId = testSysAdmin.Id;
		insert testCG1;
		
		CollaborationGroup testCG2 = new CollaborationGroup();
		testCG2.Name = 'test OOR Chatter Group 1';
		testCG2.CollaborationType = 'private';
		testCG2.OwnerId = testSysAdmin.Id;
		insert testCG2;
		
		CollaborationGroup testOORManagerCG = new CollaborationGroup();
		testOORManagerCG.Name = 'test OOR Manager Chatter Group 1';
		testOORManagerCG.CollaborationType = 'private';
		testOORManagerCG.OwnerId = testSysAdmin.Id;
		insert testOORManagerCG;
		
		ChatterUserTriggerHelper.ALL_USER_CHATTER_GROUPS.add(testCG1.Name);
		ChatterUserTriggerHelper.OOR_SALES_CHATTER_GROUPS.add(testCG2.Name);
		ChatterUserTriggerHelper.OOR_DIR_CHATTER_GROUPS_MAP.put(testSysAdmin.UserRole.Name, testOORManagerCG.Name);
		verifyChatterGroupCount(testCG1,1);
		verifyChatterGroupCount(testCG2,1);
		verifyChatterGroupCount(testOORManagerCG,1);
		
		// test insert
		User u1 = getTestUser();
		u1.ProfileId = oorProfileId;
		insert u1;
		
		verifyChatterGroupCount(testCG1,2);
		verifyChatterGroupCount(testCG2,2);
		verifyChatterMembership(testCG1, new List<User>{u1}, 1);
		verifyChatterMembership(testCG2, new List<User>{u1}, 1);
		
		u1.ManagerId = testSysAdmin.Id;
		update u1;
		
		// test batch insert
		List<User> uList = new List<User>();
		for(Integer i = 0; i < 200; i++)
		{
			User ui = getTestUser();
			ui.Username = i + ui.UserName;
			ui.CommunityNickname = i + ui.CommunityNickname;
			ui.Alias = i + ui.Alias;
			ui.ProfileId = testProfileId;
		   uList.add(ui);
		}
		
		insert uList;
		
		verifyChatterGroupCount(testCG1,202);
		verifyChatterMembership(testCG1, uList, 200);
		
		// test update
		User newOwner = uList[0];
		Test.startTest();
		
		System.runAs(testSysAdmin)
		{
		   // test insert new user with user role
			User u2 = getTestUser();
			u2.ProfileId = testProfileId;
			u2.UserRoleId = testRoleId;
			insert u2;
			
		   u1.IsActive = false;
		   update u1;
		   
		   testCG1.OwnerId = newOwner.Id;
		   update testCG1;
		   
		   update newOwner;
		}
		
		Test.stopTest();
		
		verifyChatterGroupCount(testCG1,202);
		verifyChatterMembership(testCG1, new List<User>{u1}, 0);
	}
	
	private static void verifyChatterGroupCount(CollaborationGroup cg, Integer i)
	{
		// to get the latest values
		cg = [SELECT MemberCount FROM CollaborationGroup  WHERE Id = :cg.Id];
		              
		system.assertEquals(i,cg.MemberCount);
	}
	
	private static void verifyChatterMembership(CollaborationGroup cg, List<User> u, Integer i)
	{
		Integer mc = [SELECT Count() FROM CollaborationGroupMember 
		              WHERE CollaborationGroupId = :cg.Id AND MemberId IN :u];
		              
		system.assertEquals(i,mc);
	}
}